package com.gopay.common.trace.helper;

import com.gopay.common.trace.TraceLog;
import com.gopay.common.trace.TraceLogUtils;
import com.gopay.common.trace.def.BinaryAnnotation;
import com.gopay.common.trace.def.Span;
import com.gopay.common.trace.def.Tracer;
import com.gopay.common.trace.enums.TraceType;
import com.gopay.common.trace.support.LogContext;
import com.gopay.common.util.SwitchUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author ddh02
 * @LogAbstractHelper
 * @2017/5/18 15:28  www.gopay.com.cn Inc.All rights reserved.
 */


public abstract class LogAbstractHelper {

    protected Logger logger = null;
    protected LogContext logContext = LogContext.getContext();
    protected Tracer tracer = Tracer.getTracer();
    protected long startTime = System.currentTimeMillis();
    protected Integer count = null;
    protected String spanName ;
    protected String threadName = Thread.currentThread().getName();
    protected boolean isExecute = true; //是否 记录
    protected  Span span = null;
    protected  String tid = logContext.getTid();

    protected Span ps = null; //父

    protected boolean globalSwitch; //全局开关

    public LogAbstractHelper() {
        globalSwitch = !SwitchUtils.traceSwitchOff();
        ///这里 从环境变量中取  配置参数 进行转换
        logger = LoggerFactory.getLogger(this.getClass());
    }


    public void beforeT(Object... args) {
        if (!globalSwitch) {
            return;
        }

        long start = System.currentTimeMillis();

        before(args);

        //TraceLogUtils.debugLog(this.getClass().getName() + "=before=耗时：{}", System.currentTimeMillis() - start);
    }


    public void afterT(Object... args) {
        if (!globalSwitch) {
            return;
        }
        long start = System.currentTimeMillis();

        after(args);
        //TraceLogUtils.debugLog(this.getClass().getName() + "=after=" + "耗时：{}", System.currentTimeMillis() - start);
    }

    public void exT(Throwable throwable) {
        if (!globalSwitch) {
            return;
        }
        try {
            ex(throwable);
        } catch (Exception e) {
            printSelfException(e, "处理异常时 自身抛出异常！");
        }
    }


    /**
     * 中间执行器，目前 只有springmvc会用到 === 已从模型中 扣除了
     * @param args
     */
    public void middleT(Object... args) {
        if (!globalSwitch) {
            return;
        }
        middle(args);
    }

    public void middle(Object... args) {

    }

    public abstract void before(Object... args);

    public abstract void after(Object... args);

    public abstract void ex(Throwable throwable);

    public abstract TraceType getTraceType();

    public void commonProcessEx(Throwable throwable) {
        if (span != null) {

            /*long endTime = System.currentTimeMillis();
            span.setEt(endTime);
            tracer.catchException(throwable, null, span);
            //直接屏蔽掉  这里抛异常 不需要 打印异常信息
            TraceLogUtils.log(new TraceLog(getTraceType(), endTime - span.getSt(), span, throwable));*/

            //调整异常打印的逻辑  目前这里会单独的多打印 一条数据， 将异常栈 转为string 存入span中

            tracer.catchException(throwable, null, span);

        }
    }

    /**
     * 打印采集 框架 自己的 异常信息
     * 正常情况 不应该出现 任何的异常信息
     * 如果出现 说明程序 有bug
     * @param ex
     * @param message
     */
    public void printSelfException(Exception ex, String message) {
        TraceLogUtils.log(new TraceLog(getTraceType(), -1, message, ex));
    }

    public void addBa(String key, String type, String value, Span span) {
        if (span == null) {
            return ;
        }
        BinaryAnnotation ba = new BinaryAnnotation();
        ba.setKey("order");
        ba.setType("notify.orderId");
        ba.setValue(value);
        span.addBinaryAnnotation(ba);
    }

    public void setIsExecute(boolean boo) {
        this.isExecute = boo;
    }

}
